import java.io.File;
import java.io.FileOutputStream;
/**
 * Algorithm Item Mean ALbum (AIMAL)
 * Makes a prediction based on the mean rate of an album
 * Thus if an item is part of an album, then the mean rate of all tracks 
 * in this album becomes the predicted value.
 * This Algorithm is meant as an example of how taxonomy could be used.
 * Note that the algorithm is very inefficient, it calculates the mean 
 * for an album over and over again while this could be done only once
 */
public class AIMAL extends Scheduler implements Runnable {
	int start;
	int stop;
	byte[] BLOCK;

	public AIMAL(int start, int stop) {
		this.start = start;
		this.stop = stop;
	}

	void writeBlock() {
		String FILE_NAME = BLOCK_PATH + start + ".bin";
		File out = new File(FILE_NAME);
		FileOutputStream fos;
		try {
			fos = new FileOutputStream(out);
			fos.write(BLOCK);
		} catch (Exception e) {
			e.printStackTrace();
		}

		System.out.println("Done writing: " + FILE_NAME + " @ "
				+ this.getClass());
	}

	@Override
	public void run() {
		int ilen = USERB[0].ilen;
		BLOCK = new byte[(stop - start) * ilen];

		int c = 0;
		for (int bUserID = start; bUserID < stop; bUserID++) {
			for (int i = 0; i < ilen; i++) {
				int bItemID = USERB[bUserID].items[i];

				byte pred = predict(bUserID, bItemID);

				BLOCK[c * ilen + i] = pred;
			}
			c++;
		}

		writeBlock();
	}

	public byte predict(int bUserID, int bItemID) {
		Item aItem = ITEMA[bItemID];
		double sum = 0;
		double n = 0;
		
		//If this item has an album associated with it
		if(aItem.getAlbum() != null){
			//Then: Return the mean of all votes of all items in this album
			Track[] tracks = aItem.getAlbum().getTracks();
			for (Track track : tracks){
				byte[] votes = track.votes;

				for (byte vote : votes) {
					sum += vote;
					n++;
				}
			}
		} else {
			//Else: Return the mean of all votes made on this item
			byte[] votes = aItem.votes;

			for (byte vote : votes) {
				sum += vote;
				n++;
			}
		}
		return (byte) (sum / n);
	}
}
